'语音转文字'
import base64
import json
import sys
import time
from pathlib import Path
from urllib.error import URLError
from urllib.parse import urlencode
from urllib.request import Request, urlopen
from utils import cut_voice_file


class SpeechError(Exception):
    pass


class Converter:
    def __init__(self):
        self.api_key = 'yRctqHGtOxtcFC0FhGovUUHE'
        self.secret_key = 'Y0ZLtHeAOvYa9pqjAfKjxZFcQAZ1L7Bn'
        self.token_url = 'http://openapi.baidu.com/oauth/2.0/token'
        self.asr_url = 'http://vop.baidu.com/server_api'
        self.timer = time.perf_counter
        self.token = self.fetch_token()

    def fetch_token(self):
        SCOPE = 'audio_voice_assistant_get'  # 有此scope表示有asr能力，没有请在网页里勾选，非常旧的应用可能没有
        params = {
            'grant_type': 'client_credentials',
            'client_id': self.api_key,
            'client_secret': self.secret_key
        }
        post_data = urlencode(params)
        post_data = post_data.encode('utf-8')
        req = Request(self.token_url, post_data)
        try:
            f = urlopen(req)
            result_str = f.read()
        except URLError as err:
            print('token http response http code : ' + str(err.code))
            result_str = err.read()
        result_str = result_str.decode()

        result = json.loads(result_str)
        if ('access_token' in result.keys() and 'scope' in result.keys()):
            if SCOPE and (not SCOPE in result['scope'].split(' ')
                          ):  # SCOPE = False 忽略检查
                raise SpeechError('scope is not correct')
            return result['access_token']
        else:
            raise SpeechError(
                'MAYBE API_KEY or SECRET_KEY not correct: access_token or scope not found in token response'
            )

    def _speech(self, f, DEV_PID=1537, RATE=16000):
        '识别音频文件,wave格式,时长1m以内'
        #DEV_PID = 1537  # 1537 表示识别普通话，使用输入法模型。根据文档填写PID，选择语言及识别模型
        CUID = '3314765'

        speech_data = []
        with open(f, 'rb') as speech_file:
            speech_data = speech_file.read()

        length = len(speech_data)
        if length == 0:
            raise SpeechError('file %s length read 0 bytes' % f)
        speech = base64.b64encode(speech_data)

        speech = str(speech, 'utf-8')
        params = {
            'dev_pid': DEV_PID,
            #"lm_id" : LM_ID,    #测试自训练平台开启此项
            'format': 'wav',
            'rate': RATE,
            'token': self.token,
            'cuid': CUID,
            'channel': 1,
            'speech': speech,
            'len': length
        }
        post_data = json.dumps(params, sort_keys=False)
        req = Request(self.asr_url, post_data.encode('utf-8'))
        req.add_header('Content-Type', 'application/json')
        try:
            begin = self.timer()
            f = urlopen(req)
            result_str = json.loads(str(f.read(), 'utf-8'))['result'][0]
        except URLError as err:
            print('asr http response http code : ' + str(err.code))
            result_str = ''
        return result_str

    def speech(self, f):
        result = []
        for _f in cut_voice_file(f):
            result.append(self._speech(_f))
            Path(_f).unlink()
        return ''.join(result)


if __name__ == "__main__":
    c = Converter()
    t = c.speech(r'D:\FFOutput\source.mp3')
    with open('d:/result.txt', 'w') as f:
        f.write(t)